package com.korion.android.devicedemon.core

import android.app.Activity
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.telephony.SmsManager
import android.util.Log
import android.widget.Toast
import androidx.core.app.ActivityCompat
import com.korion.android.devicedemon.MainActivity
import java.text.SimpleDateFormat


object SmsUtils {

    private const val TAG = "SmsUtils"

    const val SMS_READ_PERMISSION_CODE = 0x1
    const val SMS_SEND_PERMISSION_CODE = 0x2
    const val SMS_RECEIVE_PERMISSION_CODE = 0x4

    private val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")


    /**
     * content://sms/inbox     收件箱
     * content://sms/sent      已发送
     * content://sms/draft     草稿
     * content://sms/outbox    发件箱
     */
    fun readSms(context: Context){
        val smsInbox = Uri.parse("content://sms/inbox")
        val cr = context.contentResolver
        val projection = arrayOf("_id", "address", "person", "body", "date", "type")
        val cur = cr.query(smsInbox, projection, null, null, "date desc")
        if (cur != null) {
            val numberIndex = cur.getColumnIndex("address")
            val nameIndex = cur.getColumnIndex("person")
            val bodyIndex = cur.getColumnIndex("body")
            while (cur.moveToNext()) {
                val number = cur.getString(numberIndex)
                val name = cur.getString(nameIndex)
                val body = cur.getString(bodyIndex)
                Log.d(TAG, "number:$number, $body")
            }
            Log.d(TAG, "共${cur.count}条短信")
        }
    }

    private const val SENT_SMS_ACTION = "SENT_SMS_ACTION"
    private const val DELIVERED_SMS_ACTION = "DELIVERED_SMS_ACTION"
    private const val KEY_SMS_DIVIDE_INDEX = "sms_divide_index"
    private const val KEY_SMS_DIVIDE_COUNT = "sms_divide_count"
    private const val KEY_SMS_SEND_TIME = "sms_send_time"

    fun sendSms(context: Context, phone: String, message: String){
        if (phone.isEmpty() || message.isEmpty()) {
            return
        }

        val smsManager = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
            val id = SmsManager.getDefaultSmsSubscriptionId()
            SmsManager.getSmsManagerForSubscriptionId(id)
        } else {
            SmsManager.getDefault()
        }
        SMSSendResultReceiver.register(context)
        val strings = smsManager.divideMessage(message)
        if (strings.size > 1) {
            val sendTime = System.currentTimeMillis()
            val requestCode = (sendTime/1000L).toInt()
            val intents = ArrayList<PendingIntent>()
            for (index in 0 until strings.size) {
                val sendPI = Intent(SENT_SMS_ACTION).let {
                    it.putExtra(KEY_SMS_DIVIDE_INDEX, index)
                    it.putExtra(KEY_SMS_DIVIDE_COUNT, strings.size)
                    it.putExtra(KEY_SMS_SEND_TIME, sendTime)
                    PendingIntent.getBroadcast(context, requestCode, it,
                        PendingIntent.FLAG_MUTABLE)
                }
                intents.add(index, sendPI)
            }
            smsManager.sendMultipartTextMessage(phone, null, strings, intents, null)
        } else {
            val sendTime = System.currentTimeMillis()
            val requestCode = (sendTime/1000L).toInt()
            strings.forEachIndexed { index, it ->
                val sendPI = Intent(SENT_SMS_ACTION).let {
                    it.putExtra(KEY_SMS_DIVIDE_INDEX, index)
                    it.putExtra(KEY_SMS_DIVIDE_COUNT, strings.size)
                    it.putExtra(KEY_SMS_SEND_TIME, sendTime)
                    PendingIntent.getBroadcast(context, requestCode, it,
                        PendingIntent.FLAG_MUTABLE)
                }
                val deliveryPI = Intent(DELIVERED_SMS_ACTION).let {
                    it.putExtra(KEY_SMS_DIVIDE_INDEX, index)
                    it.putExtra(KEY_SMS_DIVIDE_COUNT, strings.size)
                    it.putExtra(KEY_SMS_SEND_TIME, sendTime)
                    PendingIntent.getBroadcast(context, requestCode, it,
                        PendingIntent.FLAG_MUTABLE)
                }
                Log.d(TAG, "send text message: time=$sendTime, index=$index, $it")
                smsManager.sendTextMessage(phone, null, it , sendPI, deliveryPI)
            }
        }
    }

    fun formatTime(timestamp: Long): String{
        return dateFormat.format(timestamp)
    }

    class SMSSendResultReceiver: BroadcastReceiver() {

        companion object {

            val instance = SMSSendResultReceiver()
            fun register(context: Context) {
                if (!instance.hasRegister) {
                    context.registerReceiver(instance, IntentFilter(SENT_SMS_ACTION))
                    context.registerReceiver(instance, IntentFilter(DELIVERED_SMS_ACTION))
                    instance.hasRegister = true
                }
            }
        }

        private var hasRegister = false
        override fun onReceive(context: Context?, intent: Intent) {
            if (intent.action == SENT_SMS_ACTION) {
                val index = intent.getIntExtra(KEY_SMS_DIVIDE_INDEX, 0)
                val count = intent.getIntExtra(KEY_SMS_DIVIDE_COUNT, 1)
                val time = intent.getLongExtra(KEY_SMS_SEND_TIME, 0)
                when(resultCode) {
                    Activity.RESULT_OK -> {
                        Log.d(TAG, "send success, sendTime=${time}, index=$index")
//                        Toast.makeText(context,  "短信发送成功(${index+1}/$count)", Toast.LENGTH_SHORT).show();
                    }
                    SmsManager.RESULT_ERROR_GENERIC_FAILURE,
                    SmsManager.RESULT_ERROR_RADIO_OFF,
                    SmsManager.RESULT_ERROR_NULL_PDU -> {
                        Log.e(TAG, "send failed, error: $resultCode, sendTime=${time}, index=$index")
//                        Toast.makeText(context, "短信发送失败(${index+1}/$count", Toast.LENGTH_SHORT).show()
                    }
                    else -> {
                        Log.e(TAG, "send failed, error: $resultCode, sendTime=${time}, index=$index")
//                        Toast.makeText(context, "短信发送失败(${index+1}/$count", Toast.LENGTH_SHORT).show()
                    }
                }
            } else if (intent.action == DELIVERED_SMS_ACTION) {
                val index = intent.getIntExtra(KEY_SMS_DIVIDE_INDEX, 0)
                val count = intent.getIntExtra(KEY_SMS_DIVIDE_COUNT, 1)
                val time = intent.getLongExtra(KEY_SMS_SEND_TIME, 0)
                Log.d(TAG, "sms has delivered, sendTime=${time}, index=$index, count=$count")
            }
        }
    }

    fun checkSmsPermission(context: Activity, permissionCode: Int, request: Boolean = false): Boolean {
        val permissions = mutableListOf<String>()
        if ((permissionCode and SMS_READ_PERMISSION_CODE) != 0) {
            permissions.add(android.Manifest.permission.READ_SMS)
        }
        if ((permissionCode and SMS_SEND_PERMISSION_CODE) != 0) {
            permissions.add(android.Manifest.permission.READ_PHONE_STATE)
            permissions.add(android.Manifest.permission.SEND_SMS)
        }
        if ((permissionCode and SMS_RECEIVE_PERMISSION_CODE) != 0) {
            permissions.add(android.Manifest.permission.RECEIVE_SMS)
        }
        if (permissions.isEmpty()) return false
        val requestPermissions = mutableListOf<String>()
        permissions.forEach {
            if (ActivityCompat.checkSelfPermission(context, it) != PackageManager.PERMISSION_GRANTED ) {
                requestPermissions.add(it)
            }
        }
        if (requestPermissions.isEmpty()) {
            return true
        }
        if (request) {
//            ActivityCompat.requestPermissions(this, requestPermissions.toTypedArray(), permissionCode)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                Log.d(TAG, "request permission:$requestPermissions")
                ActivityCompat.requestPermissions(context, requestPermissions.toTypedArray(), permissionCode)
            }
        }
        return false
    }

}